Add upstream fix for shader crash with multivolume
authorElvis Stansvik <elvis.stansvik@orexplore.com>
Fri, 5 Aug 2022 22:12:19 +0000 (00:12 +0200)
committerElvis Stansvik <elvis.stansvik@orexplore.com>
Fri, 5 Aug 2022 22:12:19 +0000 (00:12 +0200)
debian/patches/120_fix_shader_crash.patch [new file with mode: 0644]
debian/patches/series

diff --git a/debian/patches/120_fix_shader_crash.patch b/debian/patches/120_fix_shader_crash.patch
new file mode 100644 (file)
index 0000000..69c3f6b
--- /dev/null
@@ -0,0 +1,163 @@
+commit bc4d0fec4f791fb198ff316849aaf3faba24b45a
+Author: Gaspard Thevenon <gaspard.thevenon@kitware.com>
+Date:   Thu Feb 10 10:19:39 2022 +0100
+
+    Fix shader crash in Multi Volume Rendering without GradientTF
+    
+    When using OpenGLGPUVolumeRayCastMapper with a MultiVolume,
+    not specifying a gradient opacity TF produced an error in
+    the composed shader (no argument would be given to functions which expected one),
+    and nothing was rendered, although this TF is supposed to be optional.
+    
+    This commit fixes this by adding tests during the declarations of
+    those functions inside the shader, and by changing their signatures as needed.
+    Therefore, when no gradient opacity TF is given, no argument is expected
+    and none is given.
+
+diff --git a/Rendering/VolumeOpenGL2/vtkOpenGLGPUVolumeRayCastMapper.cxx b/Rendering/VolumeOpenGL2/vtkOpenGLGPUVolumeRayCastMapper.cxx
+index cdcec460ef..dfc65de04b 100644
+--- a/Rendering/VolumeOpenGL2/vtkOpenGLGPUVolumeRayCastMapper.cxx
++++ b/Rendering/VolumeOpenGL2/vtkOpenGLGPUVolumeRayCastMapper.cxx
+@@ -2415,7 +2415,8 @@ void vtkOpenGLGPUVolumeRayCastMapper::ReplaceShaderCompute(
+       vtkvolume::ComputeGradientOpacityMulti1DDecl(this->AssembledInputs));
+     vtkShaderProgram::Substitute(fragmentShader, "//VTK::ComputeColor::Dec",
+-      vtkvolume::ComputeColorMultiDeclaration(this->AssembledInputs));
++      vtkvolume::ComputeColorMultiDeclaration(
++        this->AssembledInputs, vol->GetProperty()->HasGradientOpacity()));
+     vtkShaderProgram::Substitute(fragmentShader, "//VTK::ComputeLighting::Dec",
+       vtkvolume::ComputeLightingMultiDeclaration(ren, this, vol, numComps, independentComponents,
+@@ -2970,6 +2971,23 @@ bool vtkOpenGLGPUVolumeRayCastMapper::vtkInternal::UpdateInputs(vtkRenderer* ren
+     this->ForceTransferInit();
+   }
++  if (this->MultiVolume)
++  {
++    bool hasGradient = this->Parent->AssembledInputs[0].Volume->GetProperty()->HasGradientOpacity();
++    for (auto& item : this->Parent->AssembledInputs)
++    {
++      if (item.second.Volume->GetProperty()->HasGradientOpacity() != hasGradient)
++      {
++        vtkGenericWarningMacro(
++          "Current implentation of vtkOpenGLGPUVolumeRayCastMapper does not support MultiVolume "
++          "where some volumes have a gradient opacity function and some others don't. "
++          "Rendering of the MultiVolume is disabled.");
++        success = false;
++        break;
++      }
++    }
++  }
++
+   return success;
+ }
+@@ -3106,7 +3124,10 @@ void vtkOpenGLGPUVolumeRayCastMapper::GPURender(vtkRenderer* ren, vtkVolume* vol
+   this->Impl->MultiVolume = multiVol && this->GetInputCount() > 1 ? multiVol : nullptr;
+   this->Impl->ClearRemovedInputs(renWin);
+-  this->Impl->UpdateInputs(ren, vol);
++  if (!this->Impl->UpdateInputs(ren, vol))
++  {
++    return;
++  }
+   this->Impl->UpdateSamplingDistance(ren);
+   this->Impl->UpdateTransfer2DYAxisArray(ren, vol);
+   this->Impl->UpdateTransferFunctions(ren);
+diff --git a/Rendering/VolumeOpenGL2/vtkVolumeShaderComposer.h b/Rendering/VolumeOpenGL2/vtkVolumeShaderComposer.h
+index 766f36ab63..3406bfb431 100644
+--- a/Rendering/VolumeOpenGL2/vtkVolumeShaderComposer.h
++++ b/Rendering/VolumeOpenGL2/vtkVolumeShaderComposer.h
+@@ -1054,10 +1054,24 @@ std::string ComputeLightingMultiDeclaration(vtkRenderer* vtkNotUsed(ren), vtkVol
+   int lightingComplexity)
+ {
+   vtkVolumeProperty* volProperty = vol->GetProperty();
+-  std::string shaderStr = std::string("\
++
++  std::string shaderStr = std::string();
++
++  // if no gradient TF is needed, don't add it into the function signature
++  if (volProperty->HasGradientOpacity())
++  {
++    shaderStr += std::string("\
+       \nvec4 computeLighting(vec3 texPos, vec4 color, const in sampler2D gradientTF, const in sampler3D volume, const int volIdx, int component)\
+       \n  {\
+       \n  vec4 finalColor = vec4(0.0);");
++  }
++  else
++  {
++    shaderStr += std::string("\
++      \nvec4 computeLighting(vec3 texPos, vec4 color, const in sampler3D volume, const int volIdx, int component)\
++      \n  {\
++      \n  vec4 finalColor = vec4(0.0);");
++  }
+   // Shading for composite blending only
+   int const shadeReqd = volProperty->GetShade() &&
+@@ -1243,7 +1257,8 @@ std::string ComputeColorDeclaration(vtkRenderer* vtkNotUsed(ren),
+ }
+ //--------------------------------------------------------------------------
+-std::string ComputeColorMultiDeclaration(vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap& inputs)
++std::string ComputeColorMultiDeclaration(
++  vtkOpenGLGPUVolumeRayCastMapper::VolumeInputMap& inputs, bool useGradientTF)
+ {
+   std::ostringstream ss;
+   int i = 0;
+@@ -1274,13 +1289,28 @@ std::string ComputeColorMultiDeclaration(vtkOpenGLGPUVolumeRayCastMapper::Volume
+   }
+   else
+   {
+-    ss << "vec4 computeColor(vec3 texPos, vec4 scalar, float opacity, const in sampler2D colorTF, "
+-          "const in sampler2D gradientTF, const in sampler3D volume, const int volIdx)\n"
+-          "{\n"
+-          "  return clamp(computeLighting(texPos, vec4(texture2D(colorTF,\n"
+-          "                         vec2(scalar.w, 0.0)).xyz, opacity), gradientTF, volume, "
+-          "volIdx, 0), 0.0, 1.0);\n"
+-          "}\n";
++    if (useGradientTF)
++    {
++      ss
++        << "vec4 computeColor(vec3 texPos, vec4 scalar, float opacity, const in sampler2D colorTF, "
++           "const in sampler2D gradientTF, const in sampler3D volume, const int volIdx)\n"
++           "{\n"
++           "  return clamp(computeLighting(texPos, vec4(texture2D(colorTF,\n"
++           "                         vec2(scalar.w, 0.0)).xyz, opacity), gradientTF, volume, "
++           "volIdx, 0), 0.0, 1.0);\n"
++           "}\n";
++    }
++    else
++    {
++      ss
++        << "vec4 computeColor(vec3 texPos, vec4 scalar, float opacity, const in sampler2D colorTF, "
++           "const in sampler3D volume, const int volIdx)\n"
++           "{\n"
++           "  return clamp(computeLighting(texPos, vec4(texture2D(colorTF,\n"
++           "                         vec2(scalar.w, 0.0)).xyz, opacity), volume, "
++           "volIdx, 0), 0.0, 1.0);\n"
++           "}\n";
++    }
+   }
+   return ss.str();
+@@ -1828,14 +1858,18 @@ std::string ShadingMultipleInputs(
+         if (property->GetTransferFunctionMode() == vtkVolumeProperty::TF_1D)
+         {
++          std::string gradientopacity_param = (property->HasGradientOpacity())
++            ? input.GradientOpacityTablesMap[0] + std::string(", ")
++            : std::string();
++
+           toShaderStr << "        g_srcColor.a = computeOpacity(scalar,"
+                       << input.OpacityTablesMap[0]
+                       << ");\n"
+                          "        if (g_srcColor.a > 0.0)\n"
+                          "        {\n"
+                          "          g_srcColor = computeColor(texPos, scalar, g_srcColor.a, "
+-                      << input.RGBTablesMap[0] << ", " << input.GradientOpacityTablesMap[0] << ", "
+-                      << "in_volume[" << i << "], " << i << ");\n";
++                      << input.RGBTablesMap[0] << ", " << gradientopacity_param << "in_volume[" << i
++                      << "], " << i << ");\n";
+           if (property->HasGradientOpacity())
+           {
index ee1cfee6756d008acb902bf26756ea2f1b3c5e0b..1efd5d3312b1150902050959c0303c1f30b3d83f 100644 (file)
@@ -11,3 +11,4 @@
 98_fix_mpi4py.py
 99_fix_ftbfs.patch
 110_vtk9_netcdf.patch
+120_fix_shader_crash.patch